<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>设计模式 - 单例模式（`Singleton Pattern`） | 爪哇干货分享</title>
    <meta name="generator" content="VuePress 1.9.7">
    <link rel="icon" href="/favicon.ico">
    <script charset="utf-8" async="async" src="/js/jquery.min.js"></script>
    <script charset="utf-8" async="async" src="/js/global.js"></script>
    <script charset="utf-8" async="async" src="/js/fingerprint2.min.js"></script>
    <script charset="utf-8" async="async" src="https://s9.cnzz.com/z_stat.php?id=1278232949&amp;web_id=1278232949"></script>
    <script>
              var _hmt = _hmt || [];
              (function() {
                var hm = document.createElement("script");
                hm.src = "https://hm.baidu.com/hm.js?e68b39347be2339192f80082c317901e";
                var s = document.getElementsByTagName("script")[0];
                s.parentNode.insertBefore(hm, s);
              })();
            </script>
    <meta name="description" content="包含: Java 基础，面试小册，Spring源码解析，中间件原理">
    <meta property="article:modified_time" content="2022-03-30T11:44:00.000Z">
    <meta property="og:title" content="设计模式 - 单例模式（Singleton Pattern）">
    <meta property="og:type" content="article">
    <meta property="og:url" content="/md/dev-spec/pattern/2_singleton.html">
    <meta name="twitter:title" content="设计模式 - 单例模式（Singleton Pattern）">
    <meta name="twitter:url" content="/md/dev-spec/pattern/2_singleton.html">
    <meta name="twitter:card" content="summary_large_image">
    <meta name="robots" content="all">
    <meta name="author" content="janker">
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
    <meta http-equiv="Pragma" content="no-cache">
    <meta http-equiv="Expires" content="0">
    <meta name="keywords" content="爪哇干货分享,  中间件, Spring, Java基础, 面试小册">
    <meta name="apple-mobile-web-app-capable" content="yes">
    
    <link rel="preload" href="/assets/css/0.styles.b854e512.css" as="style"><link rel="preload" href="/assets/css/styles.css?v=1648640762568" as="style"><link rel="preload" href="/assets/js/cg-styles.js?v=1648640762568" as="script"><link rel="preload" href="/assets/js/cg-app.js?v=1648640762568" as="script"><link rel="preload" href="/assets/js/cg-4.js?v=1648640762568" as="script"><link rel="preload" href="/assets/js/cg-3.js?v=1648640762568" as="script"><link rel="preload" href="/assets/js/cg-19.js?v=1648640762568" as="script"><link rel="preload" href="/assets/js/cg-5.js?v=1648640762568" as="script"><link rel="preload" href="/assets/js/cg-6.js?v=1648640762568" as="script">
    <link rel="stylesheet" href="/assets/css/0.styles.b854e512.css"><link rel="stylesheet" href="/assets/css/styles.css?v=1648640762568">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">爪哇干货分享</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/md/other/guide-to-reading.html" class="nav-link">
  导读
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Java" class="dropdown-title"><span class="title">Java</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/java/interview/book.html" class="nav-link">
  面经手册
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="方法" class="dropdown-title"><span class="title">方法</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/dev-spec/pattern/1_overview.html" class="nav-link">
  设计模式
</a></li></ul></div></div><div class="nav-item"><a href="/md/about/me/about-me.html" class="nav-link">
  关于
</a></div><div class="nav-item"><a href="https://github.com/janker0718/ShareJava" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/md/other/guide-to-reading.html" class="nav-link">
  导读
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="Java" class="dropdown-title"><span class="title">Java</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/java/interview/book.html" class="nav-link">
  面经手册
</a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="方法" class="dropdown-title"><span class="title">方法</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/md/dev-spec/pattern/1_overview.html" class="nav-link">
  设计模式
</a></li></ul></div></div><div class="nav-item"><a href="/md/about/me/about-me.html" class="nav-link">
  关于
</a></div><div class="nav-item"><a href="https://github.com/janker0718/ShareJava" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>设计模式</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/md/dev-spec/pattern/1_overview.html" class="sidebar-link">设计模式 - 概述</a></li><li><a href="/md/dev-spec/pattern/2_singleton.html" aria-current="page" class="active sidebar-link">设计模式 - 单例模式（Singleton Pattern）</a></li><li><a href="/md/dev-spec/pattern/3_factory.html" class="sidebar-link">设计模式 - 工厂模式（Factory Pattern）</a></li><li><a href="/md/dev-spec/pattern/4_abstract-factory.html" class="sidebar-link">设计模式 - 抽象工厂模式（Abstract Factory Pattern）</a></li></ul></section></li></ul> </aside> <div><main class="page"> <div class="theme-default-content content__default"><h1 id="单例模式-singleton-pattern"><a href="#单例模式-singleton-pattern" class="header-anchor">#</a> 单例模式（Singleton Pattern）</h1> <p></p><div class="table-of-contents"><ul><li><a href="#概述">概述</a><ul><li><a href="#意图">意图</a></li><li><a href="#解决的问题点">解决的问题点</a></li><li><a href="#关键思路">关键思路</a></li><li><a href="#优缺点">优缺点</a></li><li><a href="#使用场景">使用场景</a></li></ul></li><li><a href="#实现">实现</a><ul><li><a href="#_1-编写核心类-singleobject">1. 编写核心类 SingleObject</a></li><li><a href="#_2-从-singleton-类获取唯一的对象。">2. 从 singleton 类获取唯一的对象。</a></li><li><a href="#执行结果">执行结果</a></li></ul></li><li><a href="#单例模式的几种实现方式">单例模式的几种实现方式</a><ul><li><a href="#_1-懒汉式-线程不安全">1. 懒汉式，线程不安全</a></li><li><a href="#_2-懒汉式-线程安全">2. 懒汉式，线程安全</a></li><li><a href="#_3-饿汉式">3. 饿汉式</a></li><li><a href="#_4、双检锁-双重校验锁-dcl-即-double-checked-locking">4、双检锁/双重校验锁（DCL，即 double-checked locking）</a></li><li><a href="#_5-登记式-静态内部类">5. 登记式/静态内部类</a></li><li><a href="#_6-枚举">6. 枚举</a></li></ul></li></ul></div><p></p> <blockquote><p>单例模式（Singleton Pattern）是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式，它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类，该类负责创建自己的对象，同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式，可以直接访问，不需要实例化该类的对象。</p></blockquote> <div class="custom-block warning"><p class="custom-block-title">注意</p> <ol><li>单例类只能有一个实例。</li> <li>单例类必须自己创建自己的唯一实例。</li> <li>单例类必须给所有其他对象提供这一实例。</li></ol></div> <h2 id="概述"><a href="#概述" class="header-anchor">#</a> 概述</h2> <h3 id="意图"><a href="#意图" class="header-anchor">#</a> 意图</h3> <p>保证一个类仅有一个实例，并提供一个访问它的全局访问点。</p> <h3 id="解决的问题点"><a href="#解决的问题点" class="header-anchor">#</a> 解决的问题点</h3> <p>一个全局使用的类频繁地创建与销毁。</p> <h3 id="关键思路"><a href="#关键思路" class="header-anchor">#</a> 关键思路</h3> <ul><li>判断系统是否已经有这个单例，如果有则返回，如果没有则创建。</li> <li>构造函数是私有的。</li></ul> <h3 id="优缺点"><a href="#优缺点" class="header-anchor">#</a> 优缺点</h3> <ol><li>优点</li></ol> <ul><li>在内存里只有一个实例，减少了内存的开销，尤其是频繁的创建和销毁实例（比如管理学院首页页面缓存）。</li> <li>避免对资源的多重占用（比如写文件操作）。</li></ul> <ol start="2"><li>缺点</li></ol> <ul><li>没有接口，不能继承，与单一职责原则冲突，一个类应该只关心内部逻辑，而不关心外面怎么样来实例化。</li></ul> <h3 id="使用场景"><a href="#使用场景" class="header-anchor">#</a> 使用场景</h3> <ol><li>要求生产唯一序列号。</li> <li>WEB 中的计数器，不用每次刷新都在数据库里加一次，用单例先缓存起来。</li> <li>创建的一个对象需要消耗的资源过多，比如 <code>I/O</code> 与数据库的连接等。</li></ol> <div class="custom-block warning"><p class="custom-block-title">注意</p> <p><code>getInstance()</code> 方法中需要使用同步锁 <code>synchronized (Singleton.class)</code> 防止多线程同时进入造成 <code>instance</code> 被多次实例化。</p></div> <h2 id="实现"><a href="#实现" class="header-anchor">#</a> 实现</h2> <p>我们将创建一个 <code>SingleObject</code> 类。<code>SingleObject</code> 类有它的私有构造函数和本身的一个静态实例。</p> <p><code>SingleObject</code> 类提供了一个静态方法，供外界获取它的静态实例。<code>SingletonPatternDemo</code> 类使用 <code>SingleObject</code> 类来获取 <code>SingleObject</code> 对象。</p> <p><img alt="" data-src="https://cdn.jsdelivr.net/gh/janker0718/image_store@master/img/20220329235948.png" loading="lazy" class="lazy"></p> <h3 id="_1-编写核心类-singleobject"><a href="#_1-编写核心类-singleobject" class="header-anchor">#</a> 1. 编写核心类 SingleObject</h3> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SingleObject</span> <span class="token punctuation">{</span>
    <span class="token comment">//创建 SingleObject 的一个对象</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">SingleObject</span> instance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">SingleObject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token comment">//让构造函数为 private，这样该类就不会被实例化</span>
    <span class="token keyword">private</span> <span class="token class-name">SingleObject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span>

    <span class="token comment">//获取唯一可用的对象</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">SingleObject</span> <span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token keyword">return</span> instance<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">showMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
        <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">&quot;Hello World!&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>

<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><h3 id="_2-从-singleton-类获取唯一的对象。"><a href="#_2-从-singleton-类获取唯一的对象。" class="header-anchor">#</a> 2. 从 singleton 类获取唯一的对象。</h3> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">SingletonPatternDemo</span> <span class="token punctuation">{</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">void</span> <span class="token function">main</span><span class="token punctuation">(</span><span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token comment">//不合法的构造函数</span>
        <span class="token comment">//编译时错误：构造函数 SingleObject() 是不可见的</span>
        <span class="token comment">//SingleObject object = new SingleObject();</span>

        <span class="token comment">//获取唯一可用的对象</span>
        <span class="token class-name">SingleObject</span> object <span class="token operator">=</span> <span class="token class-name">SingleObject</span><span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token comment">//显示消息</span>
        object<span class="token punctuation">.</span><span class="token function">showMessage</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h3 id="执行结果"><a href="#执行结果" class="header-anchor">#</a> 执行结果</h3> <p>执行程序，输出结果：</p> <div class="language-shell line-numbers-mode"><pre class="language-shell"><code>Hello World<span class="token operator">!</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h2 id="单例模式的几种实现方式"><a href="#单例模式的几种实现方式" class="header-anchor">#</a> 单例模式的几种实现方式</h2> <h3 id="_1-懒汉式-线程不安全"><a href="#_1-懒汉式-线程不安全" class="header-anchor">#</a> 1. 懒汉式，线程不安全</h3> <ul><li>是否 Lazy 初始化：<strong>是</strong></li> <li>是否多线程安全：<strong>否</strong></li> <li>实现难度：<strong>易</strong></li></ul> <div class="custom-block tip"><p class="custom-block-title">提示</p> <p>这种方式是最基本的实现方式，这种实现最大的问题就是不支持多线程。因为没有加锁 <code>synchronized</code>，所以严格意义上它并不算单例模式。 这种方式 <code>lazy loading</code> 很明显，不要求线程安全，在多线程不能正常工作。</p></div> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">LazyUnsafeSingleton</span> <span class="token punctuation">{</span>

    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">LazyUnsafeSingleton</span> instance<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">LazyUnsafeSingleton</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span>

    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">LazyUnsafeSingleton</span> <span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>instance <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            instance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LazyUnsafeSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> instance<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p>接下来介绍的几种实现方式都支持多线程（<strong>线程安全</strong>），但是在性能上有所差异。</p> <h3 id="_2-懒汉式-线程安全"><a href="#_2-懒汉式-线程安全" class="header-anchor">#</a> 2. 懒汉式，线程安全</h3> <ul><li>是否 Lazy 初始化：<strong>是</strong></li> <li>是否多线程安全：<strong>是</strong></li> <li>实现难度：<strong>易</strong></li></ul> <blockquote><p>描述：这种方式具备很好的 <strong>lazy loading</strong>，能够在多线程中很好的工作，但是，效率很低，99% 情况下不需要同步。</p></blockquote> <p><strong>优缺点</strong></p> <ul><li>优点：第一次调用才初始化，避免内存浪费。</li> <li>缺点：必须加锁 <code>synchronized</code> 才能保证单例，但加锁会影响效率。</li></ul> <p><code>getInstance()</code> 的性能对应用程序不是很关键（该方法使用不太频繁）。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">LazySafeSingleton</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">LazySafeSingleton</span> instance<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">LazySafeSingleton</span> <span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">synchronized</span> <span class="token class-name">LazySafeSingleton</span> <span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>instance <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            instance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">LazySafeSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> instance<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><h3 id="_3-饿汉式"><a href="#_3-饿汉式" class="header-anchor">#</a> 3. 饿汉式</h3> <ul><li>是否 Lazy 初始化：<strong>否</strong></li> <li>是否多线程安全：<strong>是</strong></li> <li>实现难度：<strong>易</strong></li></ul> <blockquote><p>描述：这种方式比较常用，但容易产生垃圾对象。</p></blockquote> <p><strong>优缺点</strong></p> <ul><li>优点：没有加锁，执行效率会提高。</li> <li>缺点：类加载时就初始化，浪费内存。</li></ul> <p>它基于 classloader 机制避免了多线程的同步问题，不过，<code>instance</code> 在类装载时就实例化，虽然导致类装载的原因有很多种，在单例模式中大多数都是调用 <code>getInstance</code> 方法， 但是也不能确定有其他的方式（或者其他的静态方法）导致类装载，这时候初始化 <code>instance</code> 显然没有达到 <code>lazy loading</code> 的效果。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">HungrySingleton</span> <span class="token punctuation">{</span>
    
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token class-name">HungrySingleton</span> instance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HungrySingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">HungrySingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">HungrySingleton</span> <span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> instance<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><h3 id="_4、双检锁-双重校验锁-dcl-即-double-checked-locking"><a href="#_4、双检锁-双重校验锁-dcl-即-double-checked-locking" class="header-anchor">#</a> 4、双检锁/双重校验锁（DCL，即 double-checked locking）</h3> <ul><li>JDK 版本：<strong>JDK1.5 起</strong></li> <li>是否 Lazy 初始化：<strong>是</strong></li> <li>是否多线程安全：<strong>是</strong></li> <li>实现难度：<strong>较复杂</strong></li></ul> <blockquote><p>描述：这种方式采用双锁机制，安全且在多线程情况下能保持高性能。</p></blockquote> <p><code>getInstance()</code> 的性能对应用程序很关键。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">DCLSingleton</span> <span class="token punctuation">{</span>
    
    <span class="token keyword">private</span> <span class="token keyword">volatile</span> <span class="token keyword">static</span> <span class="token class-name">DCLSingleton</span> singleton<span class="token punctuation">;</span>
    <span class="token keyword">private</span> <span class="token class-name">DCLSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token class-name">DCLSingleton</span> <span class="token function">getSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>singleton <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">synchronized</span> <span class="token punctuation">(</span><span class="token class-name">DCLSingleton</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                <span class="token keyword">if</span> <span class="token punctuation">(</span>singleton <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
                    singleton <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">DCLSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                <span class="token punctuation">}</span>
            <span class="token punctuation">}</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> singleton<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><h3 id="_5-登记式-静态内部类"><a href="#_5-登记式-静态内部类" class="header-anchor">#</a> 5. 登记式/静态内部类</h3> <ul><li>是否 Lazy 初始化：<strong>是</strong></li> <li>是否多线程安全：<strong>是</strong></li> <li>实现难度：<strong>一般</strong></li></ul> <blockquote><p>描述：这种方式能达到双检锁方式一样的功效，但实现更简单。对静态域使用延迟初始化，应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况，双检锁方式可在实例域需要延迟初始化时使用。</p></blockquote> <p>这种方式同样利用了 <code>classloader</code> 机制来保证初始化 <code>instance</code> 时只有一个线程，它跟第 <code>3</code> 种方式不同的是：第 <code>3</code> 种方式只要 <code>Singleton</code> 类被装载了，那么 <code>instance</code> 就会被实例化（没有达到 <code>lazy loading</code> 效果），而这种方式是 <code>Singleton</code> 类被装载了，<code>instance</code> 不一定被初始化。因为 <code>SingletonHolder</code> 类没有被主动使用，只有通过显式调用 <code>getInstance</code> 方法时，才会显式装载 <code>SingletonHolder</code> 类，从而实例化 <code>instance</code>。想象一下，如果实例化 <code>instance</code> 很消耗资源，所以想让它延迟加载，另外一方面，又不希望在 <code>Singleton</code> 类加载时就实例化，因为不能确保 <code>Singleton</code> 类还可能在其他的地方被主动使用从而被加载，那么这个时候实例化 <code>instance</code> 显然是不合适的。这个时候，这种方式相比第 3 种方式就显得很合理。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">class</span> <span class="token class-name">StaticInnerClassSingleton</span> <span class="token punctuation">{</span>
    <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">class</span> <span class="token class-name">SingletonHolder</span> <span class="token punctuation">{</span>
        <span class="token keyword">private</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">StaticInnerClassSingleton</span> INSTANCE <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">StaticInnerClassSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">private</span> <span class="token class-name">StaticInnerClassSingleton</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span>
    <span class="token keyword">public</span> <span class="token keyword">static</span> <span class="token keyword">final</span> <span class="token class-name">StaticInnerClassSingleton</span> <span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token class-name">SingletonHolder</span><span class="token punctuation">.</span>INSTANCE<span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><h3 id="_6-枚举"><a href="#_6-枚举" class="header-anchor">#</a> 6. 枚举</h3> <ul><li><code>JDK</code> 版本：<strong>JDK1.5 起</strong></li> <li>是否 <code>Lazy</code> 初始化：<strong>否</strong></li> <li>是否多线程安全：<strong>是</strong></li> <li>实现难度：<strong>易</strong></li></ul> <blockquote><p>描述：这种实现方式还没有被广泛采用，但这是实现单例模式的最佳方法。它更简洁，自动支持序列化机制，绝对防止多次实例化。</p></blockquote> <p>这种方式是 <code>Effective Java</code> 作者 <code>Josh Bloch</code> 提倡的方式，它不仅能避免多线程同步问题，而且还自动支持序列化机制，防止反序列化重新创建新的对象，绝对防止多次实例化。不过，由于 <code>JDK1.5</code> 之后才加入 <code>enum</code> 特性，用这种方式写不免让人感觉生疏，在实际工作中，也很少用。</p> <p>不能通过 <code>reflection attack</code> 来调用私有构造方法。</p> <div class="language-java line-numbers-mode"><pre class="language-java"><code><span class="token keyword">public</span> <span class="token keyword">enum</span> <span class="token class-name">EnumSingleton</span> <span class="token punctuation">{</span>
    INSTANCE<span class="token punctuation">;</span>
    <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">whateverMethod</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><div class="custom-block tip"><p class="custom-block-title">TIP</p> <p>经验之谈：一般情况下，不建议使用第 1 种和第 2 种懒汉方式，建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading 效果时，才会使用第 5 种登记方式。如果涉及到反序列化创建对象时，可以尝试使用第 6 种枚举方式。如果有其他特殊的需求，可以考虑使用第 4 种双检锁方式。</p></div></div> <footer class="page-edit"><div class="edit-link"><a href="https://github.com/janker0718/ShareJava/edit/master/docs/md/dev-spec/pattern/2_singleton.md" target="_blank" rel="noopener noreferrer">在 GitHub 上编辑此页</a> <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></div> <div class="last-updated"><span class="prefix">上次更新: </span> <span class="time">3/30/2022,</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
        ←
        <a href="/md/dev-spec/pattern/1_overview.html" class="prev">
          设计模式 - 概述
        </a></span> <span class="next"><a href="/md/dev-spec/pattern/3_factory.html">
          设计模式 - 工厂模式（Factory Pattern）
        </a>
        →
      </span></p></div> </main></div> <aside class="page-sidebar"> <div class="page-side-toolbar"><div class="option-box-toc-fixed"><div class="toc-container-sidebar"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="max-height:650px"><div style="font-weight:bold;text-align:center;">设计模式 - 单例模式（Singleton Pattern）</div> <hr> <div class="toc-box"><ul class="toc-sidebar-links"><li><a href="/md/dev-spec/pattern/2_singleton.html#概述" class="toc-sidebar-link">概述</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#意图" class="toc-sidebar-link">意图</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#解决的问题点" class="toc-sidebar-link">解决的问题点</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#关键思路" class="toc-sidebar-link">关键思路</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#优缺点" class="toc-sidebar-link">优缺点</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#使用场景" class="toc-sidebar-link">使用场景</a></li></ul></li><li><a href="/md/dev-spec/pattern/2_singleton.html#实现" class="toc-sidebar-link">实现</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_1-编写核心类-singleobject" class="toc-sidebar-link">1. 编写核心类 SingleObject</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_2-从-singleton-类获取唯一的对象。" class="toc-sidebar-link">2. 从 singleton 类获取唯一的对象。</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#执行结果" class="toc-sidebar-link">执行结果</a></li></ul></li><li><a href="/md/dev-spec/pattern/2_singleton.html#单例模式的几种实现方式" class="toc-sidebar-link">单例模式的几种实现方式</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_1-懒汉式-线程不安全" class="toc-sidebar-link">1. 懒汉式，线程不安全</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_2-懒汉式-线程安全" class="toc-sidebar-link">2. 懒汉式，线程安全</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_3-饿汉式" class="toc-sidebar-link">3. 饿汉式</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_4、双检锁-双重校验锁-dcl-即-double-checked-locking" class="toc-sidebar-link">4、双检锁/双重校验锁（DCL，即 double-checked locking）</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_5-登记式-静态内部类" class="toc-sidebar-link">5. 登记式/静态内部类</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_6-枚举" class="toc-sidebar-link">6. 枚举</a></li></ul></li></ul></div></div></div></div></div> <div class="option-box"><a title="点击切换全屏" style="text-align:center;padding-left:2px;"><img src="/images/system/full.png" width="30px" class="nozoom"> <span style="color:gray;font-size:11px;font-weight:400;">全屏看</span></a></div> <div class="option-box-toc-over"><img src="/images/system/mulu.png" class="nozoom"> <span class="show-txt">目录</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="max-height:550px"><div style="font-weight:bold;text-align:center;">设计模式 - 单例模式（Singleton Pattern）</div> <hr> <div class="toc-box"><ul class="toc-sidebar-links"><li><a href="/md/dev-spec/pattern/2_singleton.html#概述" class="toc-sidebar-link">概述</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#意图" class="toc-sidebar-link">意图</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#解决的问题点" class="toc-sidebar-link">解决的问题点</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#关键思路" class="toc-sidebar-link">关键思路</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#优缺点" class="toc-sidebar-link">优缺点</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#使用场景" class="toc-sidebar-link">使用场景</a></li></ul></li><li><a href="/md/dev-spec/pattern/2_singleton.html#实现" class="toc-sidebar-link">实现</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_1-编写核心类-singleobject" class="toc-sidebar-link">1. 编写核心类 SingleObject</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_2-从-singleton-类获取唯一的对象。" class="toc-sidebar-link">2. 从 singleton 类获取唯一的对象。</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#执行结果" class="toc-sidebar-link">执行结果</a></li></ul></li><li><a href="/md/dev-spec/pattern/2_singleton.html#单例模式的几种实现方式" class="toc-sidebar-link">单例模式的几种实现方式</a><ul class="toc-sidebar-sub-headers"><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_1-懒汉式-线程不安全" class="toc-sidebar-link">1. 懒汉式，线程不安全</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_2-懒汉式-线程安全" class="toc-sidebar-link">2. 懒汉式，线程安全</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_3-饿汉式" class="toc-sidebar-link">3. 饿汉式</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_4、双检锁-双重校验锁-dcl-即-double-checked-locking" class="toc-sidebar-link">4、双检锁/双重校验锁（DCL，即 double-checked locking）</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_5-登记式-静态内部类" class="toc-sidebar-link">5. 登记式/静态内部类</a></li><li class="toc-sidebar-sub-header"><a href="/md/dev-spec/pattern/2_singleton.html#_6-枚举" class="toc-sidebar-link">6. 枚举</a></li></ul></li></ul></div></div></div></div></div> <div class="option-box"><img src="/images/system/wechat.png" class="nozoom"> <span class="show-txt">手机看</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="text-align:center"><span style="font-size:0.9rem">微信扫一扫</span> <img height="180px" src="https://api.qrserver.com/v1/create-qr-code/?data=https://www.share-java.com/md/dev-spec/pattern/2_singleton.html" style="margin:10px;">
                可以<b>手机看</b>或分享至<b>朋友圈</b></div></div></div></div> <div class="option-box"><img src="/images/system/toggle.png" width="30px" class="nozoom"> <span class="show-txt">左栏</span></div> <div class="option-box"><img src="/images/system/download-2.png" width="25px" class="nozoom"> <span class="show-txt">下资料</span> <div class="toc-container"><div class="pos-box"><div class="icon-arrow"></div> <div class="scroll-box" style="text-align:center"><span style="font-size:0.8rem;font-weight:bold;">扫描公众号，回复<span style="color:red;">“66”</span>下载<span style="color:red;">1TB+</span>学习技术资料、PDF书籍、简历模板「无任何套路」</span> <img src="https://cdn.jsdelivr.net/gh/janker0718/image_store/img/20220103214503494.png" height="180px" style="margin:10px;"> <b>公众号:</b> 爪哇干货分享
              </div></div></div></div> <div title="设计模式 - 概述" class="option-box" style="padding-left:2px;text-align:center;"><a href="/md/dev-spec/pattern/1_overview.html"><img src="/images/system/pre2.png" width="30px" class="nozoom"> <span class="show-txt">上一篇</span></a></div> <div title="设计模式 - 工厂模式（Factory Pattern）" class="option-box" style="padding-left:2px;text-align:center;"><a href="/md/dev-spec/pattern/3_factory.html"><img src="/images/system/next2.png" width="30px" class="nozoom"> <span class="show-txt">下一篇</span></a></div></div>  <div class="page-side-sitemap"><div class="option-box"><img src="/images/system/sitemap.png" class="nozoom img"> <span class="show-txt">站点图</span> <div class="sitemap-container"><h4>站点导航图
              <a href="/md/about/me/about-me.html" class="sitemap-top-link"> 关于我</a> <a href="/md/about/me/about-arch.html" class="sitemap-top-link"> 关于学习</a></h4> <table class="sitemap-table"><tr><td nowrap="nowrap"><div class="sitemap-col-group">常用搜索</div></td> <td><div class="sitemap-col-item"><a href="http://www.baidu.com/" target="_blank" title="百度">  
          百度
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="http://www.google.com/" target="_blank" title="Google">  
          Google
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="http://www.bing.com/" target="_blank" title="Bing">  
          Bing
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="https://github.com" target="_blank" title="Github">  
          Github
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="https://www.programcreek.com/java-api-examples/index.php" target="_blank" title="搜代码">  
          搜代码
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></td> <!----></tr><tr><td nowrap="nowrap"><div class="sitemap-col-group">技术社区</div></td> <td><div class="sitemap-col-item"><a href="http://www.csdn.net/" target="_blank" title="CDSN">  
          CDSN
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="http://www.cnblogs.com/" target="_blank" title="博客园">  
          博客园
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="https://www.oschina.net" target="_blank" title="OSChina">  
          OSChina
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="https://segmentfault.com/" target="_blank" title="思否">  
          思否
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="https://juejin.im" target="_blank" title="掘金">  
          掘金
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="https://www.linuxidc.com/" target="_blank" title="Linux公社">  
          Linux公社
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="https://www.ibm.com/developerworks/cn/" target="_blank" title="IBM 开发者">  
          IBM 开发者
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div><div class="sitemap-col-item"><a href="https://stackoverflow.com" target="_blank" title="StackOverflow">  
          StackOverflow
          <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg></a></div></td> <!----></tr></table></div></div></div> <!----> </aside></div><div class="global-ui"><div class="read-more-wrap" style="display:none;position:absolute;bottom:0px;z-index:9999;width:100%;margin-top:-100px;font-family:PingFangSC-Regular, sans-serif;"><div id="read-more-mask" style="position: relative; height: 200px; background: -webkit-gradient(linear, 0 0%, 0 100%, from(rgba(255, 255, 255, 0)), to(rgb(255, 255, 255)));"></div> <a id="read-more-btn" target="_self" style="position: absolute; left: 50%; top: 70%; bottom: 30px; transform: translate(-50%, -50%); width: 160px; height: 36px; line-height: 36px; font-size: 15px; text-align: center; border: 1px solid rgb(222, 104, 109); color: rgb(222, 104, 109); background: rgb(255, 255, 255); cursor: pointer; border-radius: 6px;">阅读全文</a> <div id="btw-modal-wrap" style="display: none;"><div id="btw-mask" style="position: fixed; top: 0px; right: 0px; bottom: 0px; left: 0px; opacity: 0.7; z-index: 999; background: rgb(0, 0, 0);"></div> <div id="btw-modal" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 300px; text-align: center; font-size: 13px; background: rgb(255, 255, 255); border-radius: 10px; z-index: 9999; font-family: PingFangSC-Regular, sans-serif;"><span id="btw-modal-close-btn" style="position: absolute; top: 5px; right: 15px; line-height: 34px; font-size: 34px; cursor: pointer; opacity: 0.2; z-index: 9999; color: rgb(0, 0, 0); background: none; border: none; outline: none;">×</span> <p id="btw-modal-header" style="margin-top: 40px; line-height: 1.8; font-size: 13px;">
                扫码或搜索：<span style="color: #E9405A; font-weight: bold;">爪哇干货分享</span> <br>发送：<span id="fustack-token" class="token" style="color: #e9415a; font-weight: bold; font-size: 17px; margin-bottom: 45px;">10086</span> <br>即可<span style="color: #e9415a; font-weight: bold;">立即永久</span>解锁本站全部文章</p> <img src="/images/personal/qrcode.png" style="width: 180px; margin-top: 10px; margin-bottom: 30px; border: 8px solid rgb(230, 230, 230);"></div></div></div><div class="pay-read-more-wrap" style="display:none;position:absolute;bottom:0px;z-index:9999;width:100%;margin-top:-100px;font-family:PingFangSC-Regular, sans-serif;"><div id="pay-read-more-mask" style="position: relative; height: 200px; background: -webkit-gradient(linear, 0 0%, 0 100%, from(rgba(255, 255, 255, 0)), to(rgb(255, 255, 255)));"></div> <a id="pay-read-more-btn" target="_blank" style="position: absolute; left: 50%; top: 70%; bottom: 30px; transform: translate(-50%, -50%); width: 160px; height: 36px; line-height: 36px; font-size: 15px; text-align: center; border: 1px solid rgb(222, 104, 109); color: rgb(222, 104, 109); background: rgb(255, 255, 255); cursor: pointer; border-radius: 6px;">付费阅读</a></div><!----><div></div></div></div>
    <script src="/assets/js/cg-styles.js?v=1648640762568" defer></script><script src="/assets/js/cg-4.js?v=1648640762568" defer></script><script src="/assets/js/cg-3.js?v=1648640762568" defer></script><script src="/assets/js/cg-19.js?v=1648640762568" defer></script><script src="/assets/js/cg-5.js?v=1648640762568" defer></script><script src="/assets/js/cg-6.js?v=1648640762568" defer></script><script src="/assets/js/cg-app.js?v=1648640762568" defer></script>
  </body>
</html>
